import axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig
} from 'axios';
import { useAuthStore } from '@/stores';
import router from '@/router';
import type { ApiError, ApiResponse, PaginatedResponse, RequestConfig } from '@/types/api';
import { showLoading, hideLoading } from '@/utils/loading';
import { showToast } from '@/utils/toast';

// 请求缓存
const cacheMap = new Map<string, { expire: number; data: any }>();

export class HttpClient {
  private instance: AxiosInstance;
  private cancelTokenMap = new Map<string, AbortController>();
  
  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create({
      ...config,
      withCredentials: true // 跨域携带cookie
    });
    
    this.setupInterceptors();
  }
  
  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig & RequestConfig) => {
        // 添加token
        const authStore = useAuthStore();
        if (authStore.token) {
          config.headers.Authorization = `Bearer ${authStore.token}`;
        }
        
        // 显示加载状态
        if (config.showLoading !== false) {
          showLoading();
        }
        
        // 添加取消控制器
        if (config.key) {
          const controller = new AbortController();
          this.cancelTokenMap.set(config.key, controller);
          config.signal = controller.signal;
        }
        
        return config;
      },
      (error) => {
        hideLoading();
        return Promise.reject(error);
      }
    );
    
    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        hideLoading();
        
        // 处理缓存
        if (response.config.method?.toLowerCase() === 'get' && response.config.cacheKey) {
          cacheMap.set(response.config.cacheKey, {
            expire: Date.now() + (response.config.cacheTime || 60000),
            data: response.data
          });
        }
        
        // 处理标准响应结构
        if (response.data && typeof response.data.success !== 'undefined') {
          if (response.data.success) {
            return response.data.data;
          } else {
            this.handleError(response.config, response);
            return Promise.reject(this.createApiError(response));
          }
        }
        return response.data;
      },
      (error) => {
        hideLoading();
        
        // 清除取消控制器
        if (error.config?.key) {
          this.cancelTokenMap.delete(error.config.key);
        }
        
        // 处理错误
        if (error.response) {
          this.handleError(error.config, error.response);
        } else if (error.code !== 'ERR_CANCELED') {
          // 非取消请求的错误
          showToast('网络连接错误，请检查网络设置');
        }
        
        return Promise.reject(error);
      }
    );
  }
  
  private handleError(config: AxiosRequestConfig, response: AxiosResponse) {
    const silent = (config as RequestConfig).silent;
    
    if (!silent) {
      const message = response.data?.message || '请求失败';
      showToast(message);
    }
    
    // 401处理
    if (response.status === 401) {
      const authStore = useAuthStore();
      authStore.logout();
      router.push({ name: 'Login', query: { redirect: router.currentRoute.value.fullPath } });
    }
  }
  
  private createApiError(response: AxiosResponse): ApiError {
    return {
      code: response.data?.code || response.status,
      message: response.data?.message || '请求失败',
      details: response.data?.details,
      config: response.config,
      response
    };
  }
  
  public async request<T>(config: AxiosRequestConfig & RequestConfig): Promise<T> {
    // 检查缓存
    if (config.method?.toLowerCase() === 'get' && config.cacheKey) {
      const cached = cacheMap.get(config.cacheKey);
      if (cached && cached.expire > Date.now()) {
        return cached.data;
      }
    }
    
    return this.instance.request(config);
  }
  
  public async get<T>(url: string, config?: AxiosRequestConfig & RequestConfig): Promise<T> {
    return this.request({ ...config, url, method: 'get' });
  }
  
  public async post<T>(url: string, data?: any, config?: AxiosRequestConfig & RequestConfig): Promise<T> {
    return this.request({ ...config, url, data, method: 'post' });
  }
  
  public async put<T>(url: string, data?: any, config?: AxiosRequestConfig & RequestConfig): Promise<T> {
    return this.request({ ...config, url, data, method: 'put' });
  }
  
  public async delete<T>(url: string, config?: AxiosRequestConfig & RequestConfig): Promise<T> {
    return this.request({ ...config, url, method: 'delete' });
  }
  
  public async patch<T>(url: string, data?: any, config?: AxiosRequestConfig & RequestConfig): Promise<T> {
    return this.request({ ...config, url, data, method: 'patch' });
  }
  
  public cancelRequest(key: string) {
    const controller = this.cancelTokenMap.get(key);
    if (controller) {
      controller.abort();
      this.cancelTokenMap.delete(key);
    }
  }
  
  public cancelAllRequests() {
    this.cancelTokenMap.forEach(controller => controller.abort());
    this.cancelTokenMap.clear();
  }
  
  public clearCache(key?: string) {
    if (key) {
      cacheMap.delete(key);
    } else {
      cacheMap.clear();
    }
  }
}

// 全局实例
const http = new HttpClient({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest'
  }
});

export default http;